package frame

import (
	"database/sql"
	"fmt"
	"gitee.com/git_public/vfaith/builtin/bean"
	"gitee.com/git_public/vfaith/builtin/vault"
	"gitee.com/git_public/vfaith/fount/persist"
	"gitee.com/git_public/vfaith/sugar/reflectx"
	"github.com/jmoiron/sqlx"
	"log"
)

// region 结构体定义&构造

type EntityDao[PO bean.IxBaseEntityPO] struct {
	*persist.OexSqlxAlpha
	IxBaseMapper
}

func NewEntityDao[PO bean.IxBaseEntityPO, M IxBaseMapper]() *EntityDao[PO] {
	entityDao := reflectx.NewInstance[*EntityDao[PO]]()
	entityDao.OexSqlxAlpha = persist.GetOexDefault()

	entityDao.IxBaseMapper = reflectx.NewInstance[M]()
	entityDao.InitBasicMapper()
	if entityDao.GetCondition == nil {
		log.Fatal("Error：【未实例化BasicMapper】.")
	}

	return entityDao
}

func (entityDao *EntityDao[PO]) DaoInitialize() {}

// endregion

//region 私有方法

func (entityDao *EntityDao[PO]) queryNum(param *vault.QueryParam, argsTx ...*sqlx.Tx) (int, error) {
	return entityDao.QueryNum(entityDao.GetCount(), param, argsTx...)
}

func (entityDao *EntityDao[PO]) queryList(param *vault.QueryParam, argsTx ...*sqlx.Tx) ([]PO, error) {
	var poList []PO
	err := entityDao.QueryList(&poList, entityDao.GetCollection(), param, argsTx...)
	return poList, err
}

//endregion

// region 标准CRUD

func (entityDao *EntityDao[PO]) TotalRecord(param *vault.QueryParam, argsTx ...*sqlx.Tx) (int, error) {
	//初始化查询参数
	if param == nil {
		return 0, fmt.Errorf("持久化查询vault.QueryParam不允许为空")
	}

	err := entityDao.GetCondition()(param)
	if err != nil {
		return 0, err
	}

	return entityDao.queryNum(param, argsTx...)
}

func (entityDao *EntityDao[PO]) FindList(param *vault.QueryParam, argsTx ...*sqlx.Tx) ([]PO, error) {
	//初始化查询参数
	if param == nil {
		return nil, fmt.Errorf("持久化查询vault.QueryParam不允许为空")
	}

	err := entityDao.GetCondition()(param)
	if err != nil {
		return nil, err
	}

	return entityDao.queryList(param, argsTx...)
}

func (entityDao *EntityDao[PO]) FindNumList(param *vault.QueryParam, argsTx ...*sqlx.Tx) (int, []PO, error) {
	//初始化查询参数
	if param == nil {
		return 0, nil, fmt.Errorf("持久化查询vault.QueryParam不允许为空")
	}

	err := entityDao.GetCondition()(param)
	if err != nil {
		return 0, nil, err
	}

	//从持久层获取数据
	totalNum, err1 := entityDao.queryNum(param, argsTx...)
	dataList, err2 := entityDao.queryList(param, argsTx...)

	if err1 == nil && err2 == nil {
		return totalNum, dataList, nil
	}

	return 0, nil, fmt.Errorf("数据查询异常")
}

func (entityDao *EntityDao[PO]) FindTable(param *vault.QueryParam, argsTx ...*sqlx.Tx) (*vault.TableMap, error) {
	//初始化查询参数
	if param == nil {
		return nil, fmt.Errorf("持久化查询vault.QueryParam不允许为空")
	}

	return nil, nil
}

func (entityDao *EntityDao[PO]) FindModel(id int, argsTx ...*sqlx.Tx) (PO, error) {
	//因为只有反射能够实例化泛型，性能影响所以不使用
	//var poModel PO
	//err := entityDao.Get(&poModel, entityDao.Model(), id)
	//if err != nil {
	//	log.Printf("SelectOne数据失败，异常原因：【%s】", err)
	//}
	//return poModel, err
	var poList []PO
	var err error

	if tx := persist.GetDefaultTx(argsTx); tx != nil {
		if err = tx.Select(&poList, entityDao.GetModel(), id); err != nil {
			_ = tx.Rollback()
		}
	} else {
		err = entityDao.Select(&poList, entityDao.GetModel(), id)
	}

	if len(poList) > 0 && err == nil {
		return poList[0], nil
	}
	if err != nil {
		log.Printf("SelectOne数据失败，异常原因：【%s】", err)
	}
	var poModel PO
	return poModel, err
}

func (entityDao *EntityDao[PO]) Create(poModel PO, argsTx ...*sqlx.Tx) (int64, error) {
	var result sql.Result
	var err error

	if tx := persist.GetDefaultTx(argsTx); tx != nil {
		if result, err = tx.NamedExec(entityDao.GetInsert(), poModel); err != nil {
			_ = tx.Rollback()
		}
	} else {
		result, err = entityDao.NamedExec(entityDao.GetInsert(), poModel)
	}

	if err != nil {
		log.Printf("Insert数据失败，异常原因：【%s】", err)
		return 0, err
	}
	return result.LastInsertId()
}

func (entityDao *EntityDao[PO]) Update(poModel PO, argsTx ...*sqlx.Tx) (int64, error) {
	var result sql.Result
	var err error

	if tx := persist.GetDefaultTx(argsTx); tx != nil {
		if result, err = tx.NamedExec(entityDao.GetUpdate(), poModel); err != nil {
			_ = tx.Rollback()
		}
	} else {
		result, err = entityDao.NamedExec(entityDao.GetUpdate(), poModel)
	}

	if err != nil {
		log.Printf("Update数据失败，异常原因：【%s】", err)
		return 0, err
	}
	return result.RowsAffected()
}

func (entityDao *EntityDao[PO]) Delete(id int, argsTx ...*sqlx.Tx) (int64, error) {
	var result sql.Result
	var err error

	if tx := persist.GetDefaultTx(argsTx); tx != nil {
		if result, err = tx.Exec(entityDao.GetDelete(), id); err != nil {
			_ = tx.Rollback()
		}
	} else {
		result, err = entityDao.Exec(entityDao.GetDelete(), id)
	}
	if err != nil {
		log.Printf("Delete数据失败，异常原因：【%s】", err)
		return 0, err
	}
	return result.RowsAffected()
}

// endregion

// region 辅助方法

// endregion
